package com.neuedu.redis.config;

import com.auth0.jwt.JWT;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.neuedu.redis.entity.UmsUser;
import com.neuedu.redis.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.ZoneOffset;
import java.util.Map;

/**
 * 项目 data-redis-springboot
 *
 * @author 张金山
 * @version 1.0
 * 说明
 * @date 2021/6/4 11:58
 */
@Slf4j
@Component
public class ValidateLoginInteceptor implements HandlerInterceptor  {

    @Autowired
    private RedisUtil redisUtil;


    ObjectMapper objectMapper = new ObjectMapper();



    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {


        String method = request.getMethod();

        //options 请求 直接放行
        if("options".equalsIgnoreCase(method)){
            return true;
        }

        String token = request.getHeader("token");
        if(StringUtils.isEmpty(token)){
            writeResult(response ,CommonResult.notoken());
            return false;
        }
        log.info("登录的token："+token);

        /***
         *   .withClaim("username",umsUser.getUsername())
         *                 .withClaim("password",umsUser.getPassword())
         *
         *                 .withClaim("id",umsUser.getId())                //员工的id
         *
         *
         *                 .withClaim("timestamp",umsUser.getLastlogin().toInstant(ZoneOffset.of("+8")).toEpochMilli())
         */
        String username = JWT.decode(token).getClaim("username").asString();
        String password = JWT.decode(token).getClaim("password").asString();
//        String id = JWT.decode(token).getClaim("id").asString();
        long timestamp = JWT.decode(token).getClaim("timestamp").asLong();


        String key = RedisConstants.LOGIN_PREFIX + username;
        String userJson = redisUtil.get(key);
        if(StringUtils.isEmpty(userJson)){
           writeResult( response , CommonResult.nopremiss());
           return false;
        }
        log.info("客户端的信息，用户名：{} 密码 {} 时间戳:{}",username,password,timestamp);

        log.info("缓存中的 登录信息:{} ",userJson);


        Map user = objectMapper.readValue(userJson, Map.class);

//        如果存在 则从redis中 取出user对象 和 jwt中 进行密码和时间校验

        String usernameRedis = (String) user.get("username");
        String passwordRedis = (String) user.get("password");
        long lastloginRedis = (long) user.get("lastlogin"); //1622222222222222

        log.info("Redis缓存的信息，用户名：{} 密码 {} 时间戳:{}",
                usernameRedis,
                passwordRedis,
                lastloginRedis
        );


        if(!passwordRedis.equalsIgnoreCase(password)
            ||(lastloginRedis != timestamp)
        ){
            writeResult( response , CommonResult.notoken());
            return false;
        }

        //校验通过了后，重新设置 key的过期时间

        redisUtil.expire( key, 60 *30);//刷新 key的 有效时间

        return true;
    }

    /**
     * 将结果输出到客户端，
     * @param response
     * @param notoken
     */
    private void writeResult(HttpServletResponse response, CommonResult notoken) throws IOException {

        String json = objectMapper.writeValueAsString(notoken);
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write(json);
        out.flush();
        out.close();
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }


}
